package com.shawn.springboot.integeration.netty.client.factory;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.shawn.springboot.integeration.netty.client.IClient;
import com.shawn.springboot.integeration.netty.exception.ApiException;
import com.shawn.springboot.integeration.netty.model.ServerAddress;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangjian
 * @title: AbstractClientFactory
 * @projectName 12-springboot学习
 * @description: 客户端工厂模板
 * @date 2021/4/2711:41
 */
@Slf4j
public abstract class AbstractClientFactory implements IClientFactory {
    public static final Cache<ServerAddress, IClient> LONG_CONNECT_CACHE = CacheBuilder.newBuilder()
            // 单机长连接上限，超过上限采用LRU淘汰
            .maximumSize(65535)
            .expireAfterAccess(360, TimeUnit.DAYS)
            // 设置缓存移除监听器
            .removalListener((RemovalListener<ServerAddress, IClient>) notic -> {
                log.debug("移除client[{}][{}][{}]", notic.getKey(), notic.getValue(), notic.getCause());
            }).build();

    protected abstract IClient createClient(ServerAddress address) throws ApiException;

    @Override
    public IClient get(ServerAddress address) throws ApiException {
        IClient client;
        if (address.isLongConnection()) {
            try {
                client = LONG_CONNECT_CACHE.get(address, () -> createClient(address));
            } catch (ExecutionException e) {
                log.error(e.getMessage(), e);
                throw new ApiException("连接失败");
            }
        } else {
            client = createClient(address);
        }
        return client;
    }

    @Override
    public List<IClient> getCachedClients() {
        List<IClient> clientList = new ArrayList<>();
        clientList.addAll(LONG_CONNECT_CACHE.asMap().values());
        return clientList;
    }

    @Override
    public void remove(ServerAddress address) {
        LONG_CONNECT_CACHE.invalidate(address);
    }
}
